﻿using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using cfg.card;
using kemocard.Scripts.Card.Scripts;
using kemocard.Scripts.Common;
using kemocard.Scripts.Module.Battle;
using kemocard.Scripts.MVC;
using kemocard.Scripts.Pawn;

namespace kemocard.Scripts.Card;

public partial class BaseBattleCard : BaseCard
{
    public BattleCharacter User;
    public List<BasePawn> Target;
    public int RealTimeValue;
    public int RealTimeChain = 1;
    public BaseCardScript Script;

    public BaseBattleCard(BaseCard card) : base(card.Id)
    {
        // var path = StaticUtil.GetCardScriptPath(card.Id);
        // if (!FileAccess.FileExists(path)) return;
        // var res = ResourceLoader.Load<CSharpScript>(path);
        // Script = res?.New().As<BaseCardScript>();
        Script = CardFactory.CreateCardScript(card.Id);
    }

    public BaseBattleCard() : base(null)
    {
    }

    protected Task UseCard()
    {
        return Script?.UseCard(this);
    }

    // 暴露给外部使用
    public Task UseCardExpose()
    {
        User?.UsedCardThisTurn.Add(this);
        User?.UsedCardThisBattle.Add(this);
        return UseCard();
    }

    public virtual void UpdateRealTimeValue()
    {
        var model = GameCore.ControllerMgr.GetControllerModel<BattleModel>((int)ControllerType.Battle);

        if (model is { IsInBattle: true })
        {
            var teamList = new List<BattleCharacter> { User };
            foreach (var character in model.Teammates.Where(character =>
                         !teamList.Contains(character) && character.TempUsedCard.Any(baseBattleCard =>
                             (baseBattleCard.Attribute & Attribute) != 0)))
            {
                teamList.Add(character);
            }

            RealTimeChain = teamList.Count;
        }

        if (User == null || !UseRealTimeValue)
        {
            RealTimeValue = Value;
            return;
        }

        float result = Value;
        var costRate = CostRate.GetValueOrDefault(Cost, 1f);

        if (Tags.Contains(Tag.PATTACK))
        {
            result += User.PAttack * costRate;
        }
        else if (Tags.Contains(Tag.MATTACK))
        {
            result += User.MAttack * costRate;
        }
        else if (Tags.Contains(Tag.HEAL))
        {
            result += User.Heal * costRate;
        }

        Script?.UpdateRealTimeValue(this, ref result);

        RealTimeValue = (int)(result * ChainRate.GetValueOrDefault(RealTimeChain, 1f));
    }

    public float CalculateRealTimeValue(float inValue, HashSet<Tag> inTags)
    {
        var result = inValue;
        if (User == null || !UseRealTimeValue)
        {
            return result;
        }

        float costRate = CostRate.GetValueOrDefault(Cost, 1f);

        if (inTags.Contains(Tag.PATTACK))
        {
            result += User.PAttack * costRate;
        }
        else if (inTags.Contains(Tag.MATTACK))
        {
            result += User.MAttack * costRate;
        }
        else if (inTags.Contains(Tag.HEAL))
        {
            result += User.Heal * costRate;
        }

        // Script?.UpdateRealTimeValue(this, ref result);

        // var model = GameCore.ControllerMgr.GetControllerModel<BattleModel>((int)ControllerType.Battle);
        // if (model is { IsInBattle: true })
        // {
        //     var teamList = new List<BattleCharacter> { User };
        //     foreach (var character in model.Teammates.Where(character =>
        //                  !teamList.Contains(character) && character.TempUsedCard.Any(baseBattleCard =>
        //                      (baseBattleCard.Attribute & Attribute) != 0)))
        //     {
        //         teamList.Add(character);
        //     }
        //
        //     RealTimeChain = teamList.Count;
        // }

        result = (int)(result * ChainRate.GetValueOrDefault(RealTimeChain, 1f));
        return result;
    }

    public float CalculateRealTimeValue(float inValue, float inPAttackRate = 0f, float inMAttackRate = 0f,
        float inHealRate = 0f)
    {
        var result = inValue;
        if (User == null || !UseRealTimeValue)
        {
            return result;
        }

        // float costRate = CostRate.GetValueOrDefault(Cost, 1f);
        result += User.PAttack * inPAttackRate + User.MAttack * inMAttackRate + User.Heal * inHealRate;
        result = (int)(result * ChainRate.GetValueOrDefault(RealTimeChain, 1f));
        return result;
    }

    public static Dictionary<int, float> ChainRate = new()
    {
        [2] = 1.2f,
        [3] = 1.5f,
        [4] = 1.9f,
    };

    public static Dictionary<int, float> CostRate = new()
    {
        [0] = 0.15f,
        [1] = 0.4f,
        [2] = 0.7f,
        [3] = 1f,
        [4] = 1.7f,
        [5] = 2.5f,
    };

    protected override void Dispose(bool disposing)
    {
        GameCore.EventBus.RemoveObjAllEvents(this);
        User = null;
        Target = null;
        Script = null;
        base.Dispose(disposing);
    }
}